#ifndef NR_NET_COMMAND_H
#define NR_NET_COMMAND_H

#include "nr_std.h"
#include "nr_object.h"
#include "nr_device_item_server.h"

#define NR_NET_COMMAND_START_CODE 0xfefefefe
#define NR_NET_COMMAND_VER 0xfefe0000

typedef enum nr_net_command_type
{
    NR_NET_COMMAND_NONE = 0,

    NR_NET_COMMAND_ERROR = 1000,
    
    NR_NET_COMMAND_LOGIN = 2000,
    NR_NET_COMMAND_GET_ITEMS = 2002,

    NR_NET_COMMAND_START_DATA = 2004,
    NR_NET_COMMAND_STOP_DATA = 2006,

    NR_NET_COMMAND_QUERY_DATA = 2008,
    NR_NET_COMMAND_QUERY_EVENT = 2010,
    
    NR_NET_COMMAND_LOGOUT = 2012,

    NR_NET_COMMAND_SERVER_DATA = 3000,
    NR_NET_COMMAND_SERVER_EVENT = 3002,
} nr_net_command_type_t;

typedef struct nr_net_command_header
{
    qint32 start_code;
    qint32 ver;
    nr_net_command_type_t cmd_type;
    qint32 seq_no;
    qint32 content_length;
    qint32 status_code;
    qint32 session_id;
    qint32 reserved[5];

    nr_net_command_header()
    {
        this->start_code = NR_NET_COMMAND_START_CODE;
        this->ver = NR_NET_COMMAND_VER;
        this->seq_no = 0;
        this->cmd_type = NR_NET_COMMAND_NONE;
        this->content_length = 0;
        this->status_code = 0;
        this->session_id = 0;
        memset(reserved, 0, sizeof(reserved));
    }

} nr_net_command_header_t;

/**
 * @brief Helper class that provide some useful functions
 */
class nr_net_helper
{
public:

    /**
     * @brief Convert a serializable nr_object to memory
     */
    static void object_to_byte_array(nr_object &object, QByteArray &byte_array);

    /**
     * @brief Convert a serializable nr_object to memory
     */
    static QByteArray object_to_byte_array(nr_object &object);

    /**
     * @brief Convert the memory to nr_object
     */
    static void byte_array_to_object(QByteArray &byte_array, nr_object &object);

    /**
     * @brief Create the nr_object by command type
     */
    static nr_object* create_command_by_type(nr_net_command_type cmd_type, 
        bool is_request = true);

private:
    nr_net_helper();
    Q_DISABLE_COPY(nr_net_helper);
};

class nr_request_login : public nr_object
{
public:
    QString& username() { return m_username; }
    QString& password() { return m_password; }
    
    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);

private:
    QString m_username;
    QString m_password;
};

class nr_reply_login : public nr_object
{
public:
    nr_reply_login() : nr_object(NR_OBJECT_REPLY_LOGIN) { }

    QString& cookie() { return m_cookie; }
    
    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);

public:
    QString m_cookie;
};

class nr_request_logout : public nr_object
{
public:
    nr_request_logout() : nr_object(NR_OBJECT_REQUEST_LOGOUT) { }

    QString& cookie() { return m_cookie; }
    
    virtual void serialize(QDataStream& data_stream) { }
    virtual void deserialize(QDataStream& data_stream) { }

private:
    QString m_cookie;
};

class nr_reply_logout : public nr_object
{
public:
    nr_reply_logout() : nr_object(NR_OBJECT_REPLY_LOGOUT) { }

    QString& cookie() { return m_cookie; }

    virtual void serialize(QDataStream& data_stream) { }
    virtual void deserialize(QDataStream& data_stream) { }

public:
    QString m_cookie;
};

class nr_request_get_items : public nr_object
{    
};

class nr_reply_get_items : public nr_object
{
public:
    nr_reply_get_items() : nr_object(NR_OBJECT_REPLY_GET_ITEMS) { }
    
    nr_device_item_server& root_item() { return m_item_server; }
    
    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);
    
private:
    nr_device_item_server m_item_server;
};

class nr_request_start_data : public nr_object
{
public:
    nr_request_start_data() : nr_object(NR_OBJECT_REQUEST_START_DATA) { }

    QList<nr_device_id_t>& item_list() { return m_id_list; }
    
    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);

private:
    QList<nr_device_id_t> m_id_list;
};

class nr_reply_start_data : public nr_object
{
public:
    nr_reply_start_data() : nr_object(NR_OBJECT_REPLY_START_DATA) { }

    QList<nr_device_id_t>& failed_item_list() { return m_failed_id_list; }

    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);

private:
    QList<nr_device_id_t> m_failed_id_list;
};

class nr_request_stop_data : public nr_object
{
public:
    nr_request_stop_data() : nr_object(NR_OBJECT_REQUEST_STOP_DATA) { }
    
    QList<nr_device_id_t>& item_list() { return m_id_list; }
    
    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);
    
private:
    QList<nr_device_id_t> m_id_list;
};

class nr_reply_stop_data : public nr_object
{
public:
    nr_reply_stop_data() : nr_object(NR_OBJECT_REQUEST_STOP_DATA) { }

};

class nr_request_query_data : public nr_object
{
public:
    nr_request_query_data() : nr_object(NR_OBJECT_REQUEST_QUERY_DATA) { }

    //QList<nr_device_id_t>& item_list() { return m_id_list; }
    nr_device_id_t& id() { return m_id; }
    QDateTime& begin_time() { return m_begin_time; }
    QDateTime& end_time() { return m_end_time; }

    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);

private:
    //QList<nr_device_id_t> m_id_list;
    nr_device_id_t m_id;
    QDateTime m_begin_time;
    QDateTime m_end_time;
};

class nr_reply_query_data : public nr_object
{
public:
    nr_reply_query_data() : nr_object(NR_OBJECT_REPLY_QUERY_DATA) { }

     QList<nr_data*>& data_list() { return m_data_list; }

    virtual void serialize(QDataStream& data_stream);
    virtual void deserialize(QDataStream& data_stream);

private:
    QList<nr_data*> m_data_list;
};

#endif